package com.bot.nft.module.op.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bot.common.exception.CommonException;
import com.bot.nft.core.enums.op.OpRofoEnum;
import com.bot.nft.module.op.domain.OpRofoExeLog;
import com.bot.nft.module.op.domain.OpRofoHoldLimt;
import com.bot.nft.module.op.domain.OpRofoInfo;
import com.bot.nft.module.op.domain.OpRofoList;
import com.bot.nft.module.op.domain.bo.OpRofoHoldLimtBo;
import com.bot.nft.module.op.domain.bo.OpRofoInfoBo;
import com.bot.nft.module.op.domain.bo.OpRofoListBo;
import com.bot.nft.module.op.domain.bo.OpRofoQueryBo;
import com.bot.nft.module.op.domain.vo.*;
import com.bot.nft.module.op.mapper.OpRofoExeLogMapper;
import com.bot.nft.module.op.mapper.OpRofoHoldLimtMapper;
import com.bot.nft.module.op.mapper.OpRofoInfoMapper;
import com.bot.nft.module.op.mapper.OpRofoListMapper;
import com.bot.nft.module.op.service.IRofoOpService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 描述:
 * 时间: 2023-11-27 20:17
 * 负责人: 王速
 **/
@Service
public class RofoOpServiceImpl implements IRofoOpService {

    private static final Log log = LogFactory.get();
    @Resource
    private OpRofoInfoMapper opRofoInfoMapper;
    @Resource
    private OpRofoHoldLimtMapper opRofoHoldLimtMapper;
    @Resource
    private OpRofoListMapper opRofoListMapper;
    @Resource
    private OpRofoExeLogMapper opRofoExeLogMapper;

    /**
     * 添加优先购活动信息
     *
     * @param rofoInfoBo 优先购活动信息包含：优先购活动信息标识,任务名称,快照时间等属性
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean addRofoOpInfo(OpRofoInfoBo rofoInfoBo) {
        log.info("开始添加优先购活动信息：{}", rofoInfoBo.getTaskName());
        Boolean flag = false;
        //优先购活动标识
        rofoInfoBo.setId(IdUtil.getSnowflakeNextIdStr());
        //获取优先购藏品条件项
        List<OpRofoHoldLimtBo> rofoHoldLimtInfoBoList = rofoInfoBo.getOpRofoHoldLimtBos();
        //转换entity模型
        OpRofoInfo opRofoInfo = BeanUtil.toBean(rofoInfoBo, OpRofoInfo.class);
        //添加优先购活动信息
        Integer rofo = opRofoInfoMapper.insert(opRofoInfo);
        flag = rofo > 0;


        if (rofoHoldLimtInfoBoList != null) {
            //转换优先购优先购藏品条件项entity模型
            List<OpRofoHoldLimt> rofoHoldLimtInfos = BeanUtil.copyToList(rofoHoldLimtInfoBoList, OpRofoHoldLimt.class);
            for (OpRofoHoldLimt rofoHoldLimtInfo : rofoHoldLimtInfos) {
                rofoHoldLimtInfo.setId(IdUtil.getSnowflakeNextIdStr());
                rofoHoldLimtInfo.setRofoId(opRofoInfo.getId());
            }
            //添加优先购藏品条件项信息
            boolean batch = opRofoHoldLimtMapper.insertBatch(rofoHoldLimtInfos);
            flag = batch == true;
        }
        log.info("完成添加优先购活动信息：{},{}", rofoInfoBo.getTaskName(), flag);
        return flag;
    }

    /**
     * 编辑优先购活动信息
     *
     * @param rofoInfoBo 优先购活动信息,包含：优先购活动信息标识,任务名称,快照时间等属性
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean updateRofoOpInfo(OpRofoInfoBo rofoInfoBo) {
        log.info("开始修改优先购活动信息：{}", rofoInfoBo.getTaskName());
        Boolean flag = false;
        //转换entity模型
        OpRofoInfo rofoInfo = BeanUtil.toBean(rofoInfoBo, OpRofoInfo.class);
        //获取优先购藏品条件项
        List<OpRofoHoldLimtBo> rofoHoldLimtInfoBoList = rofoInfoBo.getOpRofoHoldLimtBos();
        //修改优先购活动信息
        QueryWrapper<OpRofoInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OpRofoInfo::getId, rofoInfoBo.getId());
        int update = opRofoInfoMapper.update(rofoInfo, queryWrapper);
        flag = update > 0;
        //删除优先购藏品条件项
        QueryWrapper<OpRofoHoldLimt> holdLimtWrapper = new QueryWrapper<>();
        holdLimtWrapper.lambda().eq(OpRofoHoldLimt::getRofoId, rofoInfo.getId());
        int delete = opRofoHoldLimtMapper.delete(holdLimtWrapper);
        flag = delete > 0;

        if (rofoHoldLimtInfoBoList != null) {
            //转换优先购优先购藏品条件项entity模型
            List<OpRofoHoldLimt> rofoHoldLimtInfos = BeanUtil.copyToList(rofoHoldLimtInfoBoList, OpRofoHoldLimt.class);
            for (OpRofoHoldLimt rofoHoldLimtInfo : rofoHoldLimtInfos) {
                rofoHoldLimtInfo.setId(IdUtil.getSnowflakeNextIdStr());
                rofoHoldLimtInfo.setRofoId(rofoInfo.getId());
            }
            //添加优先购藏品条件项信息
            opRofoHoldLimtMapper.insertBatch(rofoHoldLimtInfos);
        }
        log.info("完成修改优先购活动信息：{},{}", rofoInfoBo.getTaskName(), flag);
        return flag;
    }

    /**
     * 查看优先购活动
     *
     * @param id 优先购活动标识
     * @return RofoInfoVo 优先购活动信息,包含：优先购活动信息标识,任务名称,快照时间等属性
     */
    @Override
    public OpRofoInfoVo getRofoOp(String id) {
        log.info("开始查看优先购活动信息：{}", id);
        //获取优先购活动主表信息
        OpRofoInfoVo opRofoInfoVo = opRofoInfoMapper.getRofoOp(id);
        //获取优先购活动条件项信息
        List<OpRofoHoldLimtVo> opRofoHoldLimtVos = opRofoHoldLimtMapper.getRofoHold(opRofoInfoVo.getId());
        opRofoInfoVo.setOpRofoHoldLimtVos(opRofoHoldLimtVos);
        log.info("完成查看优先购活动信息：{}", id);

        return opRofoInfoVo;


    }

    /**
     * 删除优先购活动
     *
     * @param id 优先购活动标识
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean delRofoOp(String id) {
        log.info("开始删除优先购活动信息：{}", id);
        QueryWrapper<OpRofoInfo> RofoWrapper = new QueryWrapper<>();
        RofoWrapper.lambda().eq(OpRofoInfo::getId, id);
        int delete = opRofoInfoMapper.deleteById(id);
        log.info("完成删除优先购活动信息：{}", id);
        return delete > 0;
    }

    /**
     * 查询优先购活动列表
     *
     * @param rofoQueryBo 请求参数
     * @param pageNo      当前页码
     * @param pageSize    每页条数
     * @return RofoListInfoVo* 包含：优先购活动信息标识,任务名称,快照时间等属性
     */
    @Override
    public Page<OpRofoInfoVo> queryRofoOpByPage(OpRofoQueryBo rofoQueryBo, Integer pageNo, Integer pageSize) {
        Page<OpRofoInfo> page = new Page<>(pageNo, pageSize);
        //获取活动信息
        Page<OpRofoInfoVo> voPage = opRofoInfoMapper.queryRofo(page, rofoQueryBo.getRofoName());
        //获取条件项信息
        List<OpRofoInfoVo> records = voPage.getRecords();
        for (OpRofoInfoVo opRofoInfoVo : records) {
            List<OpRofoHoldLimtVo> rofoHold = opRofoHoldLimtMapper.getRofoHold(opRofoInfoVo.getId());
            opRofoInfoVo.setOpRofoHoldLimtVos(rofoHold);
        }
        return voPage;
    }

    /**
     * 查询优先购购买资格(app端)
     *
     * @return RofoListInfoVo* 包含：优先购活动信息标识,任务名称,快照时间等属性
     */
    @Override
    public Page<OpRofoListVo> queryRofoList(OpRofoQueryBo rofoQueryBo, Integer pageNo, Integer pageSize) {
        Page<OpRofoListVo> page = new Page<>(pageNo, pageSize);
        Page<OpRofoListVo> opRofoListVoPage = opRofoListMapper.getMembershipApp(page, rofoQueryBo.getPhone(),
                rofoQueryBo.getNftId());
        return opRofoListVoPage;
    }

    /**
     * 启用优先购活动
     *
     * @param id 优先购活动标识
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean enableRofoOp(String id) {
        log.info("开始启用优先购活动信息：{}", id);
        UpdateWrapper<OpRofoInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(OpRofoInfo::getStatus, OpRofoEnum.OPENINGUP.getCode()).eq(OpRofoInfo::getId, id);
        int update = opRofoInfoMapper.update(null, updateWrapper);
        log.info("完成启用优先购活动信息：{}", id);
        return update > 0;
    }

    /**
     * 禁用优先购活动
     *
     * @param id 优先购活动标识
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean disRofoOp(String id) {
        log.info("开始启用优先购活动信息：{}", id);
        UpdateWrapper<OpRofoInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(OpRofoInfo::getStatus, OpRofoEnum.DISABLE.getCode()).eq(OpRofoInfo::getId, id);
        int update = opRofoInfoMapper.update(null, updateWrapper);
        log.info("完成启用优先购活动信息：{}", id);
        return update > 0;
    }

    /**
     * 执行优先购活动快照
     *
     * @return Boolean 成功/true，失败/false
     */
    @Override
    public Boolean exeRofoSnapshot(String id) {
        Boolean flag = false;
        //查询优先购活动信息
        OpRofoInfoVo rofoOp = opRofoInfoMapper.getRofoOp(id);

        Date snapshotTime = rofoOp.getSnapshotTime();
        Date date = new Date();
        if (snapshotTime.getTime() > date.getTime()) {
            throw new CommonException("请在快照时间后执行");
        }
        List<OpRofoHoldLimtVo> rofoHold = opRofoHoldLimtMapper.getRofoHold(rofoOp.getId());
        List<List<OpRofoListBo>> lists = new ArrayList<>();
        List<OpRofoListBo> rofoLists = null;

        //获取 会员id，截止时间，藏品数量  【一个条件 时间和藏品数量】
        for (OpRofoHoldLimtVo rofoHoldLimtVo : rofoHold) {
            String nftId = rofoHoldLimtVo.getNftId();
            Integer number = Integer.valueOf(rofoHoldLimtVo.getNumber());
            rofoLists = opRofoInfoMapper.queryRofoList(nftId, snapshotTime, number);
            //计算购买次数
            for (int i = 0; i < rofoLists.size(); i++) {
                OpRofoListBo rofoList = rofoLists.get(i);
                Integer number1 = rofoList.getNumber();
                Integer floor = (int) Math.floor((number1 / number));
                rofoList.setNumber(floor);
            }
            lists.add(rofoLists);
        }

        //判断多种是否符合全部条件
        Integer addRofo = OpRofoEnum.NAMELIST.getCode();
        Map<String, List<Integer>> map = new HashMap<>();
        List<OpRofoListBo> rofoListBody = new ArrayList<>();
        //总资格人数
        Integer sum = null;
        //将会员数据的添加到map
        if (lists.size() > OpRofoEnum.CONDITION.getCode()) {
            for (int i = 1; i < lists.size(); i++) {
                List<OpRofoListBo> rofoList = lists.get(i);
                for (OpRofoListBo rofoListBady : rofoList) {
                    List<Integer> integers = map.get(rofoListBady.getMbId());
                    if (integers == null) {
                        List<Integer> integerList = new ArrayList<>();
                        integerList.add(rofoListBady.getNumber());
                        map.put(rofoListBady.getMbId(), integerList);
                    } else {
                        integers.add(rofoListBady.getNumber());
                    }
                }
            }
            //获取会员总数
            Set<String> strings = map.keySet();
            OpRofoListBo rofoList = new OpRofoListBo();
            //根据会员id判断是否满足条件 获取会员名称 和最小购买数量
            for (String mbId : strings) {
                List<Integer> integers = map.get(mbId);
                if (integers.size() == lists.size()) {
                    Integer min = Collections.min(integers);
                    rofoList.setMbId(mbId);
                    rofoList.setNumber(min);
                    rofoListBody.add(rofoList);
                }
            }
            for (int j = 0; j < rofoListBody.size(); j++) {
                OpRofoListBo rofoList1 = rofoListBody.get(j);
                rofoList1.setId(IdUtil.getSnowflakeNextIdStr());
                rofoList1.setRofoId(rofoOp.getId());
                rofoList1.setStatus(OpRofoEnum.STATUS.getCode());
                rofoList1.setCreationTime(new Date());
            }
            if (rofoListBody.size() != 0) {
                List<OpRofoList> opRofoLists = BeanUtil.copyToList(rofoListBody, OpRofoList.class);
                addRofo = opRofoListMapper.addRofoList(opRofoLists);
                sum = rofoListBody.size();
            }

        } else {
            for (int j = 0; j < rofoLists.size(); j++) {
                OpRofoListBo rofoList1 = rofoLists.get(j);
                rofoList1.setId(IdUtil.getSnowflakeNextIdStr());
                rofoList1.setRofoId(rofoOp.getId());
                rofoList1.setStatus(OpRofoEnum.STATUS.getCode());
                rofoList1.setCreationTime(new Date());
            }
            if (rofoLists.size() != 0) {
                List<OpRofoList> opRofoLists = BeanUtil.copyToList(rofoLists, OpRofoList.class);
                addRofo = opRofoListMapper.addRofoList(opRofoLists);
                sum = rofoLists.size();
            }
        }

        //将状态改变
        UpdateWrapper<OpRofoInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("status", OpRofoEnum.EXECUTE.getCode()).eq("id", id);
        int update = opRofoInfoMapper.update(null, updateWrapper);


        //执行日志记录
        OpRofoExeLog rofoExeLog = new OpRofoExeLog();
        rofoExeLog.setId(IdUtil.getSnowflakeNextIdStr());
        rofoExeLog.setRofoId(id);
        rofoExeLog.setExecuteTime(new Date());
        Integer logStatus = addRofo > 0 ? OpRofoEnum.EXESUCCESS.getCode() : OpRofoEnum.EXEFAIL.getCode();
        rofoExeLog.setRemark(logStatus == OpRofoEnum.EXESUCCESS.getCode() ? OpRofoEnum.SUCCESSREMARK.getName() + sum
                : OpRofoEnum.FAILREMARK.getName());
        rofoExeLog.setStatus(logStatus);
        int insert = opRofoExeLogMapper.insert(rofoExeLog);
        flag = insert > 0;
        return flag;
    }

    /**
     * 查看执行日志
     *
     * @param rofoId 优先购活动标识
     * @return
     */
    @Override
    public List<OpRofoExeLogVo> getExeLog(String rofoId) {
        log.info("开始查看执行日志：{}", rofoId);
        QueryWrapper<OpRofoExeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OpRofoExeLog::getRofoId, rofoId);
        List<OpRofoExeLogVo> exeLog = opRofoExeLogMapper.selectVoList(queryWrapper);
        log.info("完成查看执行日志：{}", rofoId);
        return exeLog;
    }


    /**
     * 判断会员购买资格（app详情页）
     *
     * @param nftId
     * @param phone
     * @return
     */
    @Override
    public Boolean assessment(String nftId, String phone) {
        log.info("开始查询活动资格：{}", nftId);
        List<OpRofoListVo> rofoList = opRofoListMapper.getMembership(phone, nftId);
        log.info("完成查询活动资格：{}", nftId);
        return rofoList.size() > 0;
    }


    /**
     * 查询优先购会员资格 (app端)
     *
     * @param rofoQueryBo 请求参数
     * @param pageNo      当前页码
     * @param pageSize    每页条数
     * @return RofoListInfoVo* 包含：优先购活动信息标识,任务名称,快照时间等属性
     */
    @Override
    public Page<OpRofoOpListVo> queryAppRofoPage(OpRofoQueryBo rofoQueryBo, Integer pageNo, Integer pageSize) {

        Map<String, Integer> map = new HashMap();
        List<OpRofoListVo> rofoList = opRofoListMapper.getMembership(rofoQueryBo.getPhone(), rofoQueryBo.getNftId());

        for (int i = 0; i < rofoList.size(); i++) {
            OpRofoListVo rofoListVo = rofoList.get(i);
            map.put(rofoListVo.getRofoId(), OpRofoEnum.QUALIFIED.getCode());
        }
        Page<OpRofoOpListVo> page = new Page<>(pageNo, pageSize);
        Page<OpRofoOpListVo> rofoOpListVos = opRofoInfoMapper.queryRofoOpByPage(page, rofoQueryBo.getRofoName(),
                rofoQueryBo.getStartTime(), rofoQueryBo.getEndTime());
        for (OpRofoOpListVo rofoOpListVo : rofoOpListVos.getRecords()) {
            Integer falg = map.get(rofoOpListVo.getId());
            if (falg != null) {
                rofoOpListVo.setQualification(OpRofoEnum.QUALIFIED.getCode());
            } else {
                rofoOpListVo.setQualification(OpRofoEnum.INELIGIBILITY.getCode());
            }
        }
        return rofoOpListVos;
    }


    /**
     * 判断是否启用并未快照的任务 (计时器任务)
     */
    @Override
    public List<OpRofoInfo> exeSnapshotTask() {
        QueryWrapper<OpRofoInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OpRofoInfo::getStatus, OpRofoEnum.OPENINGUP.getCode());
        List<OpRofoInfo> opRofoInfos = opRofoInfoMapper.selectList(queryWrapper);
        return opRofoInfos;
    }


}
